package cn.com.bluemoon.daps.standard.service.impl;

import cn.com.bluemoon.daps.common.enums.BmStatus;
import cn.com.bluemoon.daps.common.exception.DapException;
import cn.com.bluemoon.daps.common.toolkit.BmAssetUtils;
import cn.com.bluemoon.daps.standard.entity.DapSystemCategory;
import cn.com.bluemoon.daps.standard.entity.DapSystemSequenceGenerate;
import cn.com.bluemoon.daps.standard.mapper.DapSystemCategoryMapper;
import cn.com.bluemoon.daps.standard.mapper.DapSystemSequenceGenerateMapper;
import cn.com.bluemoon.daps.standard.service.DapSystemSequenceGenerateService;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Optional;

/**
 * <p>
 * 编码规则表，如：指标编码规则，自动生成，规则：
 * ZB_MM_NNNNNN
 * ZB：“指标”的标识；
 * MM：代码所属于主题的代码；
 * NNNNNN：6位数字序列号，从000001开始排序；
 * 举例：ZB_ZF_000001。 服务实现类
 * </p>
 *
 * @author admin
 * @since 2020-08-18
 */
@Slf4j
@Service
@Transactional(rollbackFor = {DapException.class, Exception.class})
public class DapSystemSequenceGenerateServiceImpl extends ServiceImpl<DapSystemSequenceGenerateMapper, DapSystemSequenceGenerate>
        implements DapSystemSequenceGenerateService {
    /**
     * 序列号默认长度
     */
    public static final int MY_SERIAL_LENGTH_DEFAULT = 6;
    /**
     * 序列号初始化值
     */
    public static final int MY_SERIAL_INIT_DEFAULT = 0;
    /**
     * 序列号分割线
     */
    public static final String MY_SERIAL_SPLIT_LINE_DEFAULT = "_";

    @Resource
    private DapSystemCategoryMapper systemCategoryMapper;

    /**
     * 根据模型表生成序列号
     *
     * @param generate
     * @return
     */
    @Override
    public Optional<String> generateByModel(DapSystemSequenceGenerate generate, Boolean upperCase,
                                            String splitLine) {
        // 生成seq
        List<String> segements = Lists.newArrayList();
        segements.add(generate.getType());
        segements.add(generate.getTopicCode());
        Integer mySerial = generate.getMySerial() + 1;
        generate.setMySerial(mySerial);
        String mySerialStr = String.valueOf(mySerial);
        String mySeq = mySerialStr;
        // 长度不够的补零，否则取原值
        if (generate.getMySerialLength() > mySerialStr.length()) {
            mySeq = String.format("%0" + generate.getMySerialLength() + "d", mySerial);
        }
        segements.add(mySeq);
        String seqCode = String.join(Optional.ofNullable(splitLine).orElse(MY_SERIAL_SPLIT_LINE_DEFAULT), segements);
        return Optional.of(Optional.ofNullable(upperCase).orElse(Boolean.TRUE) ? seqCode.toUpperCase() : seqCode);
    }

    @Override
    public String getSeqByTypeAndTopicCodeAndSerial(String type,
                                                    String topicCode,
                                                    Boolean upperCase,
                                                    Integer serialLength,
                                                    Integer serialInitValue,
                                                    String splitLine) {
        return generateSequenceByDb(type, topicCode, upperCase, serialLength, serialInitValue, splitLine).orElseThrow(() -> new DapException("获取序列号失败"));
    }

    @Override
    public String getSeqByTypeAndTopicId(String type,
                                         String topicId) {
        DapSystemCategory dapSystemCategory = systemCategoryMapper.selectById(topicId);
        BmAssetUtils.notNull(dapSystemCategory, "获取主题编码失败");
        BmAssetUtils.isTrue(StringUtils.isNotBlank(dapSystemCategory.getCode()), "主题[" + dapSystemCategory.getCodeName() + "]的编码不存在，无法生成指标编码！");
        return getSeqByTypeAndTopicCodeAndSerial(type, dapSystemCategory.getCode(), null, null, null, null);
    }

    @Override
    public String getSeqByTypeAndTopicCode(String type, String topicCode) {
        return generateSequenceByDb(type, topicCode, null, null, null, null).orElseThrow(() -> new DapException("获取序列号失败"));
    }

    /**
     * 根据实体数据生成序列
     *
     * @return
     */
    private Optional<String> generateSequenceByDb(String type,
                                                  String topicCode,
                                                  Boolean upperCase,
                                                  Integer serialLength,
                                                  Integer serialInitValue,
                                                  String splitLine) {
        if (type == null || topicCode == null) {
            return Optional.empty();
        }
        DapSystemSequenceGenerate generate = getOne(Wrappers.lambdaQuery(new DapSystemSequenceGenerate())
                .eq(DapSystemSequenceGenerate::getType, type)
                .eq(DapSystemSequenceGenerate::getTopicCode, topicCode)
                .eq(DapSystemSequenceGenerate::getBmStatus, BmStatus.ON)
                .last(" limit 1")
                .orderByDesc(DapSystemSequenceGenerate::getMySerial));
        if (generate == null) {
            generate = new DapSystemSequenceGenerate();
            generate.setMySerial(Optional.ofNullable(serialInitValue).orElse(MY_SERIAL_INIT_DEFAULT));
            generate.setMySerialLength(Optional.ofNullable(serialLength).orElse(MY_SERIAL_LENGTH_DEFAULT));
            generate.setTopicCode(topicCode);
            generate.setType(type);
            generate.insert();
        }
        Optional<String> seq = generateByModel(generate, upperCase, splitLine);
        generate.setCurrentSerial(seq.orElse(null));
        generate.insertOrUpdate();
        return seq;
    }
}
